package academic.emailClient.model;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.UUID;

import academic.emailClient.model.entities.Filter;
import academic.emailClient.model.entities.Folder;
import academic.emailClient.model.entities.Meeting;
import academic.emailClient.model.entities.Message;

public interface EmailClientModel {
	/**
	 * Saves message in drafts folder
	 * @param message Message that is going to be saved
	 */
	void saveDraftMessage(Message message);
	
	/**
	 * Creates a subfolders in the folder hierarchy
	 * @param path Path where the folder will be created
	 * @param folderName name of the folder
	 */
	void createSubfolder(String path, String folderName);
	
	/**
	 * Moves message from a subfolder to another
	 * @param source path of the folder that contains the message
	 * @param destination path of the folder that is going to contain message
	 * @param messageID Message unique identifier
	 */
	void moveMessagesToSubfolders(String source, String destination, ArrayList<UUID> messageID);
	
	/**
	 * Saves message in to sent folder
	 * @param message Message that is going to be saved
	 */
	void saveToSendMessage(Message message);
	
	/**
	 * Sent an email and saves it in Sent folder
	 * @param message
	 */
	void sendMessage(Message message);
	
	/**
	 * Receives a new message and saves it to the inbox
	 * @param message Message received
	 */
	void receiveMessage(Message message);
	
	/**
	 * Deletes a message from a folder
	 * @param folderPath 
	 * @param messages List of messages that should be deleted
	 */
	void deleteMessages(String folderPath, ArrayList<UUID> messages);
	
	/**
	 * Deletes the last folder of the path 
	 * @param folderPath 
	 */
	void deleteSubFolder(String folderPath);
	
	/**
	 * Returns the Message Folder Structure
	 * @return Returns the folder hierarchy 
	 */
	Folder getFoldersHierarchy();
	
	/**
	 * Returns the message list of a specific subfolder
	 * @param folderPath
	 * @return Message ArrayList containing messages
	 */
	ArrayList<Message> getFolderContent(String folderPath);
	
	/**
	 * Returns a folder given its path
	 * @param path Folder Path
	 * @return Folder, if the folder doesn't exist will return null
	 */
	Folder getSubFolderByPath(String path);
	
	/**
	 * Returns messages that are inside inbox and were received
	 */
	ArrayList<Message> getIboxMessages();
	
	/**
	 * Returns a list of subfolders with its path
	 * @return the key of the hashmap is a visible name of the folder path and the value is the real path
	 */
	HashMap<String, String> getAllSubfoldersPaths();
	
	/**
	 * Search messages that match with an specific criteria given in an user query
	 * @param userQuery ArrayList with search criteria
	 * @return Array list of messages that match with the criteria
	 */
	ArrayList<Message> searchNewQuery(ArrayList<String> userQuery);
	
	/**
	 * Returns an arrayList of the meetings that the user has created and are inside the model
	 * @return Meetings
	 */
	HashMap<UUID, Meeting> getMeetings();
	
	/**
	 * Creates a new meeting inside the model
	 * @param meeting New meeting that must be added to the model
	 */
	boolean createMeeting(Meeting meeting);
	
	/**
	 * Sends to server a request to update a meeting.
	 * @param meeting Meeting that has been modified
	 * @return Returns false if the meeting doesn't exist anymore
	 */
	boolean requestUpdateMeeting(Meeting meeting);
	
	/**
	 * Cancel a meeting that has already created
	 * @param meetingID Unique identification of the meeting
	 */
	boolean cancelMeeting(UUID meetingID);
	
	/**
	 * Receives a meeting cancellation from the owner and applies it
	 * @param meetingID Unique identification of the meeting, user must be invited to the meeting
	 */
	boolean receiveMeetingCancellation(UUID meetingID);
	
	/**
	 * Creates a new filter inside model to be executed periodically
	 * @param newFilter Must have all it's attributes filled, and the name must be unique.
	 * @return Returns true, if the filter can be created
	 */
	boolean createFilter(Filter newFilter);
	
	/**
	 * Deletes a filter of the list of filters created in the model
	 * @param filterName Filter must exist in the model
	 * @return Returns true, if the filter can be deleted
	 */
	boolean deleteFilter(String filterName);
	
	/**
	 * Update information of an existent filter. Name of the filter must not be changed because
	 * it's the key of the object 
	 * @param filter Filter with new information except name
	 * @return Returns true if filter can be updated
	 */
	boolean updateFilter(Filter filter);
	
	/**
	 * Returns a list of filters created in the model
	 * @return
	 */
	ArrayList<Filter> getFilters();
	
	/**
	 * Executes and save a Filter that the user wants to save
	 * @param filter Filter that is going to be saved and executed
	 */
	void executeFilter(Filter filter);
	
	/**
	 * Runs filters every amount of time
	 */
	void runFiltersExecution();

	/**
	 * Receives a new meeting
	 * @param meeting
	 */
	void receiveMeeting(Meeting meeting);
	
	/**
	 * Accept a Meeting received sending a message to the owner of the meeting
	 * @param meetingID
	 */
	void acceptMeeting(UUID meetingID);
	
	/**
	 * Sends the declination notification to be erased from it
	 * @param meetingID Meeting must exists
	 */
	void declineMeeting(UUID meetingID);
	
	/**
	 * Receive a meeting declination and updates the meeting
	 * @param meetingID Meeting must exists
	 * @param decliner Attendee that is declining invitation
	 */
	void receiveMeetingDeclination(UUID meetingID, String decliner);
	
	/**
	 * Update a meeting that has already been created inside the list of meetings of the user
	 * @param meeting Meeting that keeps and id of an existent meeting but the rest of the information can be changed
	 */
	boolean updateMeeting(Meeting meeting);
	
	/**
	 * Confirms update of a meeting to the source of the change
	 * @param meeting
	 * @return
	 */
	boolean confirmMeetingUpdate(Meeting meeting);
	
}
